/*
 * Copyright (C) 2013 rdrrlabs gmail com,
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package serv

import (
    "appengine"
    "appengine/user"
    "fmt"
    "html/template"
    "log"
    "net/http"
    "strings"
    "time"
)

func init() {
    http.HandleFunc("/", handleBootstrapRoot)
}


func Choice(b bool, a1, a2 int) int {
    if b {
        return a1
    }
    return a2
}

//------------------------------

var mBootstrapTemplate *template.Template


func handleBootstrapRoot(w http.ResponseWriter, r *http.Request) {
    var err error
    startTS := time.Now()
    log.SetPrefix("## serv: ")
    c := appengine.NewContext(r)
    u := user.Current(c)
    _path := r.URL.Path

    // DEBUG
    log.Printf("## ROOT %v, path='%v', query='%v'", r.Method, _path, r.URL.RawQuery)

    type tabInfo struct {
        Title   string
        URL     string
        Active  string  // "active" for the current tab handler
    }

    // Data for filling the main page HTML template
    var data struct {
        Email       string
        UserTooltip string
        SignLink    string
        LogoutLink  string
        Timestamp   string
        AppVersion  string
        ErrStr      string
        Tabs        []tabInfo
        TabName     string
        TabContent  template.HTML
        TabPathJS   string
    }

    // Find whether user is signed, compute sign-in or log-out links
    isSigned := false
    if u == nil {
        url, err := user.LoginURL(c, r.URL.String())
        if err != nil {
            log.Println("## user.LoginURL failed: ", err)
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        data.SignLink = url;
    } else {
        isSigned = true
        url, err := user.LogoutURL(c, r.URL.String())
        if err != nil {
            log.Println("## user.LogoutURL failed: ", err)
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        data.Email = u.Email
        data.LogoutLink = url
    }

    // Find our db user info to get groups, adjust if user is admin
    var accessInfo = FetchAccessInfo(c, u)
    var isAdmin  = isSigned && user.IsAdmin(c)
    if isAdmin {
        // Users marked as admin in the AppEngine console have view + create rights too
        accessInfo.Add(GroupAdmin)
        accessInfo.Add(GroupView)
        accessInfo.Add(GroupCreate)
    }
    if accessInfo.Groups != nil {
        data.UserTooltip = "Groups: " + strings.Join(accessInfo.Groups, ", ")
        if isAdmin {
            data.UserTooltip += " [GA]"
        }
    }

    returnCode := http.StatusInternalServerError

    // Find the request handler for the current request, depending on user group.
    urlBase, urlRest, handler, err := FindRequestHandler(r, isSigned, &accessInfo)

    if handler != nil {
        if handler.Handler().Is(HandlerIsTab) {
            // This is a handler for a UI tab. We'll display the main UI template.
            log.Printf("## UI-tab match found for %v %v => %v", r.Method, urlBase, urlRest)

            data.TabContent = handler.CreateTab(r, c, &accessInfo)

            data.Tabs = make([]tabInfo, 0)
            for _, h := range FindHandlers(r, true, isSigned, &accessInfo) {
                ti := tabInfo { h.Handler().Title, h.Handler().URL, "" }
                if h == handler {
                    ti.Active = "active"
                    data.TabPathJS = "timeri" + strings.Replace(h.Handler().Title, " ", "", -1)
                    data.TabName = h.Handler().Title
                }
                data.Tabs = append(data.Tabs, ti)

                // DEBUG
                log.Printf("## Add UI Tab: %v", ti)
            }
            err = nil
            returnCode = http.StatusOK

        } else {
            // This is a handler for a UI-less request (e.g. Ajax, etc.)
            log.Printf("## UI-less match found for %v %v => %v", r.Method, urlBase, urlRest)
            returnCode, err = handler.ProcessRequest(w, r, c, &accessInfo, urlBase, urlRest)
            if err != nil {
                if returnCode == http.StatusOK {
                    returnCode = http.StatusInternalServerError
                }
                log.Printf("## HTTP Reply with [%d] '%s'", returnCode, err.Error())
                http.Error(w, err.Error(), returnCode)
            } else if returnCode > 0 {
                w.WriteHeader(returnCode)
            }
            return
        }
    }

    data.Timestamp = fmt.Sprintf("%v \u2014 \u0394 %v", time.Now().Format("2006-01-02 15:04:05"), time.Since(startTS))
    data.AppVersion = "v" + appengine.VersionID(c)

    if isAdmin {
        data.AppVersion += " | " + appengine.ServerSoftware()
    }
    if err != nil && isAdmin {
        // For admins, display errors if any
        data.ErrStr = err.Error()
    }

    if mBootstrapTemplate == nil {
        mBootstrapTemplate = template.Must(template.New("serv_bootstrap.html").ParseFiles("serv/serv_bootstrap.html"))
    }

    err = mBootstrapTemplate.Execute(w, data)
    if err != nil {
        http.Error(w, err.Error(), returnCode)
    }
}


